using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Xml;
namespace ICSharpCode.TextEditor.Document
{
    public class HighlightingManager
    {
        private ArrayList syntaxModeFileProviders = new ArrayList();
        private static HighlightingManager highlightingManager;
        private Hashtable highlightingDefs = new Hashtable();
        private Hashtable extensionsToName = new Hashtable();
        public event EventHandler ReloadSyntaxHighlighting;
        public Hashtable HighlightingDefinitions
        {
            get
            {
                return this.highlightingDefs;
            }
        }

        public static HighlightingManager Manager
        {
            get
            {
                return HighlightingManager.highlightingManager;
            }
        }

        public static ICollection HighlightingNames
        {
            get
            {
                return HighlightingManager.highlightingManager.highlightingDefs.Keys;
            }
        }

        public DefaultHighlightingStrategy DefaultHighlighting
        {
            get
            {
                return (DefaultHighlightingStrategy)this.highlightingDefs["Default"];
            }
        }
        static HighlightingManager()
        {
            HighlightingManager.highlightingManager = new HighlightingManager();
            HighlightingManager.highlightingManager.AddSyntaxModeFileProvider(new ResourceSyntaxModeProvider());
        }
        public HighlightingManager()
        {
            this.CreateDefaultHighlightingStrategy();
        }
        public void AddSyntaxModeFileProvider(ISyntaxModeFileProvider syntaxModeFileProvider)
        {
            foreach(SyntaxMode current in syntaxModeFileProvider.SyntaxModes)
            {
                this.highlightingDefs[current.Name] = new DictionaryEntry(current, syntaxModeFileProvider);
                string[] extensions = current.Extensions;
                for(int i = 0 ; i < extensions.Length ; i++)
                {
                    string text = extensions[i];
                    this.extensionsToName[text.ToUpperInvariant()] = current.Name;
                }
            }
            if(!this.syntaxModeFileProviders.Contains(syntaxModeFileProvider))
            {
                this.syntaxModeFileProviders.Add(syntaxModeFileProvider);
            }
        }
        public void AddHighlightingStrategy(IHighlightingStrategy highlightingStrategy)
        {
            this.highlightingDefs[highlightingStrategy.Name] = highlightingStrategy;
            string[] extensions = highlightingStrategy.Extensions;
            for(int i = 0 ; i < extensions.Length ; i++)
            {
                string text = extensions[i];
                this.extensionsToName[text.ToUpperInvariant()] = highlightingStrategy.Name;
            }
        }
        public void ReloadSyntaxModes()
        {
            this.highlightingDefs.Clear();
            this.extensionsToName.Clear();
            this.CreateDefaultHighlightingStrategy();
            foreach(ISyntaxModeFileProvider syntaxModeFileProvider in this.syntaxModeFileProviders)
            {
                syntaxModeFileProvider.UpdateSyntaxModeList();
                this.AddSyntaxModeFileProvider(syntaxModeFileProvider);
            }
            this.OnReloadSyntaxHighlighting(EventArgs.Empty);
        }
        private void CreateDefaultHighlightingStrategy()
        {
            DefaultHighlightingStrategy defaultHighlightingStrategy = new DefaultHighlightingStrategy();
            defaultHighlightingStrategy.Extensions = new string[0];
            defaultHighlightingStrategy.Rules.Add(new HighlightRuleSet());
            this.highlightingDefs["Default"] = defaultHighlightingStrategy;
        }
        private IHighlightingStrategy LoadDefinition(DictionaryEntry entry)
        {
            SyntaxMode syntaxMode = (SyntaxMode)entry.Key;
            ISyntaxModeFileProvider syntaxModeFileProvider = (ISyntaxModeFileProvider)entry.Value;
            DefaultHighlightingStrategy defaultHighlightingStrategy = null;
            try
            {
                XmlTextReader syntaxModeFile = syntaxModeFileProvider.GetSyntaxModeFile(syntaxMode);
                if(syntaxModeFile == null)
                {
                    throw new HighlightingDefinitionInvalidException("Could not get syntax mode file for " + syntaxMode.Name);
                }
                defaultHighlightingStrategy = HighlightingDefinitionParser.Parse(syntaxMode, syntaxModeFile);
                if(defaultHighlightingStrategy.Name != syntaxMode.Name)
                {
                    throw new HighlightingDefinitionInvalidException(string.Concat(new string[]
					{
						"The name specified in the .xshd '", 
						defaultHighlightingStrategy.Name, 
						"' must be equal the syntax mode name '", 
						syntaxMode.Name, 
						"'"
					}));
                }
            }
            finally
            {
                if(defaultHighlightingStrategy == null)
                {
                    defaultHighlightingStrategy = this.DefaultHighlighting;
                }
                this.highlightingDefs[syntaxMode.Name] = defaultHighlightingStrategy;
                defaultHighlightingStrategy.ResolveReferences();
            }
            return defaultHighlightingStrategy;
        }
        internal KeyValuePair<SyntaxMode, ISyntaxModeFileProvider> FindHighlighterEntry(string name)
        {
            foreach(ISyntaxModeFileProvider syntaxModeFileProvider in this.syntaxModeFileProviders)
            {
                foreach(SyntaxMode current in syntaxModeFileProvider.SyntaxModes)
                {
                    if(current.Name == name)
                    {
                        return new KeyValuePair<SyntaxMode, ISyntaxModeFileProvider>(current, syntaxModeFileProvider);
                    }
                }
            }
            return new KeyValuePair<SyntaxMode, ISyntaxModeFileProvider>(null, null);
        }
        public IHighlightingStrategy FindHighlighter(string name)
        {
            object obj = this.highlightingDefs[name];
            if(obj is DictionaryEntry)
            {
                return this.LoadDefinition((DictionaryEntry)obj);
            }
            if(obj != null)
            {
                return (IHighlightingStrategy)obj;
            }
            return this.DefaultHighlighting;
        }
        public IHighlightingStrategy FindHighlighterForFile(string fileName)
        {
            string text = (string)this.extensionsToName[Path.GetExtension(fileName).ToUpperInvariant()];
            if(text == null)
            {
                return this.DefaultHighlighting;
            }
            object obj = this.highlightingDefs[text];
            if(obj is DictionaryEntry)
            {
                return this.LoadDefinition((DictionaryEntry)obj);
            }
            if(obj != null)
            {
                return (IHighlightingStrategy)obj;
            }
            return this.DefaultHighlighting;
        }
        protected virtual void OnReloadSyntaxHighlighting(EventArgs e)
        {
            if(this.ReloadSyntaxHighlighting != null)
            {
                this.ReloadSyntaxHighlighting(this, e);
            }
        }
    }
}
